package com.binc.testspring.common.utils;

import com.binc.testspring.common.annotation.BincNull;
import com.binc.testspring.common.annotation.DictCode;
import com.binc.testspring.common.annotation.DictConf;
import com.binc.testspring.common.handler.DictCodeProperty;
import com.binc.testspring.common.handler.DictTypeDto;
import com.binc.testspring.common.handler.IDictHandler;
import com.binc.testspring.common.pojo.service.IDictService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 这个个控制处理
 * //字典值 字段为null ,用 --代替
 */
public class NullUtils {
    private static final Logger log = LoggerFactory.getLogger(NullUtils.class);

    public NullUtils() {
    }

    //字典值 字段为null ,用 --代替
    public static <T> List<T> decode(List<T> source) {
        if (source != null && source.size() > 0) {
            Class type = source.get(0).getClass();

            Set<DictCodeProperty> dictCodes = getDictFieldByAnno(type, BincNull.class);
            List<DictTypeDto> dictTypeDtos = getDictTypeDtos(dictCodes);
            return DictUtils.decode(source).stream().map(p -> {
                return convertDict(p, dictCodes);
            }).collect(Collectors.toList());

        }
            return source;

    }

    //字典值 字段为null ,用 --代替  至于替换成什么可以用注解的参数自定义的；
    private static <T> T convertDict(T source, Set<DictCodeProperty> properties) {
        BeanWrapper sourceBw = PropertyAccessorFactory.forBeanPropertyAccess(source);
        Iterator var4 = properties.iterator();

        DictCodeProperty property;
        Object fieldValue;
        while (true) {
            if (!var4.hasNext()) {
                return source;
            }
            property = (DictCodeProperty) var4.next();
            String fieldKey = property.getName();
            fieldValue = sourceBw.getPropertyValue(fieldKey);
            try {
                if (fieldValue == null) {
                    sourceBw.setPropertyValue(property.getName(), "--");
                }
            } catch (Exception var18) {
                break;
            }
        }
        return source;
    }

    public static boolean isCode(Class source) {
        DictConf dictConf = (DictConf)source.getAnnotation(DictConf.class);
        return dictConf != null && dictConf.enable();
    }

    public static <T> T decode(T source) {
        if (source == null) {
            return null;
        } else {
            Class type = source.getClass();
            if (!isCode(type)) {
                return source;
            } else {
                DictConf dictConf = (DictConf)type.getAnnotation(DictConf.class);
                Set<DictCodeProperty> dictCodes = getDictFieldByAnno(type, DictCode.class);
                source = decodeSource(source, dictConf, dictCodes, getDictTypeDtos(dictCodes));
                return source;
            }
        }
    }

    public List<DictTypeDto> getDictTypeDtos(Class type) {
        return getDictTypeDtos(getDictFieldByAnno(type, DictCode.class));
    }

    private static List<DictTypeDto> getDictTypeDtos(Set<DictCodeProperty> dictCodes) {
        IDictService service = null;

        try {
            service = (IDictService)Global.getBean(IDictService.class);
        } catch (Exception var4) {
            log.error("请实现com.binc.testspring.base.service.IDictService接口", var4);
            return null;
        }

        List<String> types = (List)dictCodes.stream().map((p) -> {
            return p.getDictCode().code();
        }).filter((p) -> {
            return StringUtils.isNotBlank(p);
        }).collect(Collectors.toList());
        List<DictTypeDto> dictDtos = null;
        if (CollectionUtils.isNotEmpty(types)) {
            dictDtos = service.getByTypes(types);
        }

        return dictDtos;
    }

    private static <T> T decodeSource(T source, DictConf dictConf, Set<DictCodeProperty> dictCodes, List<DictTypeDto> dictDtos) {
        if (dictConf != null && dictConf.enable() && dictConf.handler() != null) {
            IDictHandler dictHandler = (IDictHandler) BeanUtils.instantiateClass(dictConf.handler());
            if (dictHandler != null) {
                if (CollectionUtils.isNotEmpty(dictDtos)) {
                    dictHandler.setSource(dictDtos);
                }

                source = (T) dictHandler.decode(source, dictCodes);
            }
        }

        return source;
    }

    private static Set<DictCodeProperty> getDictFieldByAnno(Class sourceClz, Class anno) {
        Field[] fields = getAllFields(sourceClz);
        Set<DictCodeProperty> annos = new HashSet();
        Field[] var4 = fields;
        int var5 = fields.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            Field field = var4[var6];
            field.setAccessible(true);
            Annotation hasAnno = field.getAnnotation(anno);
            if (hasAnno != null) {
                DictCodeProperty property = new DictCodeProperty();
                property.setDictCode((DictCode)hasAnno);
                property.setName(field.getName());
                annos.add(property);
            }
        }

        return annos;
    }

    private static Field[] getAllFields(Class clazz) {
        ArrayList fieldList;
        for(fieldList = new ArrayList(); clazz != null; clazz = clazz.getSuperclass()) {
            fieldList.addAll(new ArrayList(Arrays.asList(clazz.getDeclaredFields())));
        }

        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }

    private static Field[] getAllFields(Object object) {
        return getAllFields(object.getClass());
    }
}
